package org.vectrics.common.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.vectrics.SystemException;

public class FileCopy {
    private static Logger log = Logger.getLogger(FileCopy.class);

    /**
     * @deprecated Use {@link #copyFile(File, File)} instead
     */
    @Deprecated
    public static void copy(String sourceFileName, String destinationFileName) {
        File sourceFile = new File(sourceFileName);
        File destinationFile = new File(destinationFileName);
        FileInputStream source = null;
        FileOutputStream destination = null;
        byte[] buffer;
        int bytesRead;

        if (sourceFile.isDirectory()) {
            FileCopy.copyDirectory(sourceFileName, destinationFileName);
            return;
        }

        log.debug("Copying file,\r\n - From = " + sourceFileName + "\r\n - To: " + destinationFileName);
        try {
            // First make sure the specified source file
            // exists, is a file, and is readable.
            if (!sourceFile.exists() || !sourceFile.isFile()) {
                throw new SystemException("FileCopy: no such source file: " + sourceFileName);
            }
            if (!sourceFile.canRead()) {
                throw new SystemException("FileCopy: source file " + "is unreadable: " + sourceFileName);
            }

            if (destinationFile.exists()) {
                if (destinationFile.isFile()) {
                    // DataInputStream in = new DataInputStream(System.in);
                    if (!destinationFile.canWrite()) {
                        throw new SystemException("FileCopy: destination " + "file is unwriteable: "
                                + destinationFileName);
                    }
                } else {
                    throw new SystemException("FileCopy: destination " + "is not a file: " + destinationFileName);
                }
            } else {
                File parentdir = parent(destinationFile);
                if (!parentdir.exists()) {
                    FileUtil.createDirectoryIfNotExist(parentdir.getAbsolutePath());
                }
                if (!parentdir.exists()) {
                    throw new SystemException("Failed to create the parent directory: " + parentdir.getAbsolutePath());
                }

                if (!parentdir.canWrite()) {
                    throw new SystemException("FileCopy: destination " + "directory is unwriteable: "
                            + parentdir.getAbsolutePath());
                }
            }
            log.debug("If we've gotten this far, then everything is okay; we can copy the file.");
            source = new FileInputStream(sourceFile);
            destination = new FileOutputStream(destinationFile);
            // buffer = new byte[1024];
            while (true) {
                int r = source.read();
                if (r < 0) {
                    break;
                }
                destination.write(r);
            }
            log.debug("Done copying bytes, closing streams...");
        } catch (Exception ex) {
            throw new SystemException("Exception copying file", ex);
        } finally {
            log.debug("No matter what happens, always close any streams we've opened.");
            if (source != null) {
                try {
                    source.close();
                } catch (IOException e) {
                    log.error("IOException closing source file", e);
                }
            }
            if (destination != null) {
                try {
                    destination.close();
                } catch (IOException e) {
                    log.error("IOException closing destination file", e);
                }
            }
        }
    }

    // File.getParent() can return null when the file is specified without
    // a directory or is in the root directory.
    // This method handles those cases.
    private static File parent(File f) {
        String dirname = f.getParent();
        if (dirname == null) {
            if (f.isAbsolute()) {
                return new File(File.separator);
            } else {
                return new File(System.getProperty("user.dir"));
            }
        }
        return new File(dirname);
    }

    /**
     * @deprecated Use {@link #copyDirectory(File, File)} instead
     */
    @Deprecated
    public static void copyDirectory(String fromDir, String toDir) {
        log.debug("Copying directory, from = " + fromDir + "  To: " + toDir);

        File fromDirectory = new File(fromDir);
        if (fromDirectory.exists() == false) {
            throw new SystemException("Could not find director to copy from: " + fromDir);
        }

        String[] files = fromDirectory.list();
        for (int i = 0; i < files.length; i++) {
            String fileName = files[i];
            FileCopy.copy(fromDir + "/" + fileName, toDir + "/" + fileName);
        }
    }

    public static void copyDirectory(File srcDir, File destDir) {
        try {
            FileUtils.copyDirectory(srcDir, destDir);
        } catch (IOException e) {
            throw new SystemException(e);
        }
    }

    public static void copyFile(File srcFile, File destFile) {
        try {
            FileUtils.copyFile(srcFile, destFile);
        } catch (IOException e) {
            throw new SystemException(e);
        }
    }
}
